package com.baofu.paycore.biz.task;

import com.baofu.paycore.biz.notice.ProductHandler;
import com.baofu.paycore.biz.paycore.converter.BO2BOConverter;
import com.baofu.paycore.biz.paycore.handler.BaseHandler;
import com.baofu.paycore.biz.paycore.handler.impl.RechargeHandler;
import com.baofu.paycore.biz.paycore.handler.impl.RefundHandler;
import com.baofu.paycore.biz.paycore.handler.impl.UnfreezeWithdrawHandler;
import com.baofu.paycore.biz.paycore.handler.impl.WithdrawHandler;
import com.baofu.paycore.common.constant.PayCoreConstant;
import com.baofu.paycore.common.enums.BizCmdTypeEnum;
import com.baofu.paycore.common.exception.PayCoreBizException;
import com.baofu.paycore.manager.model.*;
import com.baofu.paycore.manager.model.withdraw.WithdrawBO;
import com.baofu.paycore.manager.model.withdraw.WithdrawBankBO;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import com.baofu.paycore.service.facade.enums.RequestSystemEnum;
import com.baofu.paycore.service.facade.enums.ServiceCodeEnum;
import com.google.common.base.Splitter;
import com.system.dispatch.dal.model.BizCmdDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jboss.logging.MDC;
import org.slf4j.helpers.SystemMarker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * 清分业务处理
 *
 * User: xin deng  Date: 2017/3/22 ProjectName: paycore Version: 1.0
 */
@Slf4j
@Component
public class ClearBizHandler {

    /**
     * 消费服务
     */
    @Resource(name = "webConsumerHandler")
    private BaseHandler<PayBO,RechargeBO> consumeHandler;

    /**
     * 提现处理服务
     */
    @Autowired
    private WithdrawHandler withdrawHandler;

    /**
     * 解冻提现服务
     */
    @Autowired
    private UnfreezeWithdrawHandler unfreezeWithdrawHandler;

    /**
     * 充值处理服务
     */
    @Autowired
    private RechargeHandler rechargeHandler;

    /**
     * 退款处理服务
     */
    @Autowired
    private RefundHandler refundHandler;

    /**
     * 发kafka消息服务
     */
    @Autowired
    private ProductHandler productHandler;


    public void process(BizCmdDO command) {
        MDC.put(SystemMarker.TRACE_LOG_ID, command.getTraceLogId());
        String bizDesc = BizCmdTypeEnum.explain(command.getBizType());

        log.debug("dispatch {}处理流程, command:{}", bizDesc, command);

        if (StringUtils.isEmpty(command.getBizId())) {
            log.error("{}执行Dispatch异常 command:{}", bizDesc, command);
            return;
        }

        ResponseBO responseBO;
        String requestType = null;
        String fundDetailNo = null;
        try {
            List<String> strings = Splitter.on(PayCoreConstant.BASE_CMD_SEPARATOR).splitToList(command.getBizId());
            requestType = strings.get(0);
            fundDetailNo = strings.get(1);
            log.info("{}执行开始 请求服务类型:{} 银行资金单号:{}, 第：{}次重试, 共重试{}次", bizDesc, requestType, fundDetailNo,
                    command.getRetryTimes(), command.getMaxRetryTimes());
            ServiceCodeEnum serviceCode = ServiceCodeEnum.explain(requestType);
            if (serviceCode == null) {
                log.error("暂不支持此业务：{}", requestType);
                throw new PayCoreBizException(PayCoreErrorCode.NOT_IN_SERVICE);
            }
            PayBaseBO payBaseBO;
            switch (serviceCode) {
                case WITHDRAW:
                    WithdrawBO withdrawBO = withdrawHandler.activeOrder(fundDetailNo);
                    WithdrawBankBO withdrawBankBO = withdrawBO.getWithdrawBankBO();
                    if (PayStatusEnums.SUCCESS.getCode().equals(withdrawBankBO.getStatus()) ||
                            PayStatusEnums.FAIL.getCode().equals(withdrawBankBO.getStatus())) {
                        log.info("提现银行单已最终状态:{}", withdrawBankBO.getStatus());
                        return;
                    }
                    payBaseBO = withdrawBO;
                    responseBO = withdrawHandler.withdrawTimeOut(withdrawBO, fundDetailNo);
                    break;
                case RECHARGE:
                    RechargeBO rechargeBO = rechargeHandler.activeOrder(fundDetailNo);
                    RechargeBankBO rechargeBankBO = rechargeBO.getRechargeBankBO();
                    if (PayStatusEnums.SUCCESS.getCode().equals(rechargeBankBO.getStatus()) ||
                            PayStatusEnums.FAIL.getCode().equals(rechargeBankBO.getStatus())) {
                        log.info("充值银行单已最终状态:{}", rechargeBankBO.getStatus());
                        return;
                    }
                    payBaseBO = rechargeBO;
                    responseBO = rechargeHandler.handleRechargeTimeOut(rechargeBO, fundDetailNo);
                    break;
                case REFUND:
                    RefundBO refundBO = refundHandler.activeOrder(fundDetailNo);
                    payBaseBO = refundBO;
                    responseBO = refundHandler.clearRefundTimeOut(refundBO, fundDetailNo);
                    break;
                case ISSUE_WITHDRAW:
                    WithdrawBO unfreezeWithdrawBO = unfreezeWithdrawHandler.activeOrder(fundDetailNo);
                    WithdrawBankBO withdrawBank = unfreezeWithdrawBO.getWithdrawBankBO();
                    if (PayStatusEnums.SUCCESS.getCode().equals(withdrawBank.getStatus()) ||
                            PayStatusEnums.FAIL.getCode().equals(withdrawBank.getStatus())) {
                        log.info("下发解冻提现银行单已最终状态:{}", withdrawBank.getStatus());
                        return;
                    }
                    payBaseBO = unfreezeWithdrawBO;
                    responseBO = unfreezeWithdrawHandler.withdrawTimeOut(unfreezeWithdrawBO, fundDetailNo);
                    break;
                default:
                    log.error("调清分 暂不支持此业务:{}", requestType);
                    throw new PayCoreBizException(PayCoreErrorCode.NOT_IN_SERVICE);
            }

            if (Objects.equals(PayStatusEnums.INIT.getCode(), responseBO.getStatus())) {
                log.error("本次{}未成功:{},{},{}", bizDesc, command.getBizId(), responseBO.getErrorCode(),
                        responseBO.getErrorMsg());
                throw new PayCoreBizException(PayCoreErrorCode.DISPATCH_RETRY_EXCEPTION, responseBO.getErrorMsg());
            }

            //回调支付
            payBaseBO = this.doConsume(payBaseBO, requestType);
            payBaseBO.setTradeLogId(command.getTraceLogId());
            //发送消息
            productHandler.sendKafkaMsg(BO2BOConverter.getPayMessageDTO(payBaseBO, responseBO));
        } catch (Exception e) {

            if (e instanceof PayCoreBizException && PayCoreErrorCode.RECHARGE_ORDER_IS_SUCCESS
                    .equals(((PayCoreBizException) e).getErrorCode())) {
                log.info("充值单已经成功,无序再进行补单处理,请求单号:{},{}", fundDetailNo, ((PayCoreBizException) e).getErrorCode());
                return;
            }
            log.error("{}命令执行失败 请求类型:{} 请求单号:{} 失败:{}", bizDesc, requestType, fundDetailNo, e);
            throw e;
        } finally {
            log.info("{}执行结束 业务ID:{}", bizDesc, command.getBizId());
        }
    }

    /**
     * 支付回调
     *
     * @param rechargeBO        充值订单
     */
    private PayBaseBO doConsume(PayBaseBO rechargeBO, String requestType){
        if(!Objects.equals(RequestSystemEnum.PAYCORE.getCode(),rechargeBO.getRequestSystem()) ||
                !Objects.equals(ServiceCodeEnum.RECHARGE.getCode(), requestType)){
            log.info("充值回调:{} 请求业务类型:{}",rechargeBO.getRequestSystem(), requestType);
            return rechargeBO;
        }
        //消费回调
        return consumeHandler.callBack((RechargeBO) rechargeBO);
    }
}
